home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
jnos110g.zip
/
MAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-26
|
59KB
|
2,195 lines
/* Main-level network program:
* initialization
* keyboard processing
* generic user commands
*
* Copyright 1991 Phil Karn, KA9Q
*/
#include <time.h>
#if defined(__TURBOC__) && defined(MSDOS)
#include <fcntl.h>
#include <dos.h>
#include <io.h>
#include <conio.h>
#include <ctype.h>
#include <dir.h>
#include <alloc.h>
#endif
#ifdef LINUX
#include <fcntl.h>
#endif
#include "global.h"
#ifdef ANSIPROTO
#include <stdarg.h>
#endif
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#include "ax25.h"
#include "kiss.h"
#include "enet.h"
#include "netrom.h"
#include "ftpcli.h"
#include "telnet.h"
#include "tty.h"
#include "session.h"
#include "hardware.h"
#include "bm.h"
#include "usock.h"
#include "socket.h"
#ifdef LZW
#include "lzw.h"
#endif
#include "cmdparse.h"
#include "commands.h"
#include "daemon.h"
#include "devparam.h"
#include "domain.h"
#include "files.h"
#include "main.h"
#include "mailbox.h"
#include "remote.h"
#include "trace.h"
#include "mailutil.h"
#include "smtp.h"
#include "index.h"
#include "version.h"
#ifdef XMS
#include "xms.h"
#endif
#ifdef EMS
#include "memlib.h"
#endif
#undef BETA 1
#ifdef LINUX
#define BETA 1
#endif
#ifdef BSAHAX
#define BETA 1
#endif
#if defined(__TURBOC__) || (defined __BORLANDC__)
/* Don't even think about changing the following #pragma :-) - WG7J */
#pragma option -a-
/* The following is from the Borland Runtime Library Version 3.0 :
* Copyright (c) 1987, 1990 by Borland International
*/
typedef struct
{
unsigned char windowx1;
unsigned char windowy1;
unsigned char windowx2;
unsigned char windowy2;
unsigned char attribute;
unsigned char normattr;
unsigned char currmode;
unsigned char screenheight;
unsigned char screenwidth;
unsigned char graphicsmode;
unsigned char snow;
union {
char far * p;
struct { unsigned off,seg; } u;
} displayptr;
} VIDEOREC;
extern VIDEOREC _video;
char *Screen_Address(void){
/* Might have to add some code to get the address of the virtualized
* DV screen here, if we go that route.
*/
return _video.displayptr.p;
}
#pragma option -a
#endif /* TURBOC || BORLANDC */
extern struct cmds DFAR Cmds[],DFAR Startcmds[],DFAR Stopcmds[],DFAR Attab[];
#if (!defined(MSDOS) || defined(ESCAPE)) /* PC uses F-10 key always */
static char Escape = 0x1d; /* default escape character is ^] */
#endif
#ifdef __TURBOC__
int dofstat __ARGS((void));
#endif
static char Prompt[] = "jnos> ";
char NoRead[] = "Can't read %s: %s\n";
char Badhost[] = "Unknown host %s\n";
char Badinterface[] = "Interface \"%s\" unknown\n";
char Existingiface[] = "Interface %s already exists\n";
char Nospace[] = "No space!!\n"; /* Generic malloc fail message */
char Nosversion[] = "JNOS version %s\n";
char NosLoadInfo[] = "NOS load info: CS=0x%04x DS=0x%04x";
char Noperm[] = "Permission denied.\n";
char Nosock[] = "Can't create socket\n";
char SysopBusy[] = "The sysop is busy. Try again later.\n";
char TelnetMorePrompt[] = "--more--";
char BbsMorePrompt[] = "More(N=no)? ";
char *Hostname;
char *Motd; /* Message Of The Day */
#if !defined MAILBOX || defined TTYLINKSERVER || defined TTYCALL
int Attended = TRUE; /* default to attended mode */
#else
int Attended;
#endif
int ThirdParty = TRUE; /* Allows 3rd party mail by default */
int main_exit; /* from main program (flag) */
int DosPrompt; /* Use a dos-like prompt */
int Mprunning; /* flag for other parts (domain) to signal
* that we are fully configured running.
*/
static int ErrorPause;
static int Step;
static int RmLocks = 1;
extern int StLen2;
extern char *StBuf2;
extern char *StBuf3;
#ifdef MAILBOX
#define MAXSTATUSLINES 3
#else
#define MAXSTATUSLINES 2
#endif
#ifdef STATUSWIN
int StatusLines = MAXSTATUSLINES;
#else
int StatusLines = 0;
#endif
struct proc *Cmdpp;
#ifndef LINUX
struct proc *Display;
#endif
#ifdef LZW
int Lzwmode = LZWCOMPACT;
int16 Lzwbits = LZWBITS;
#endif
#ifdef TRACE
int Tracesession = 1;
struct session *Trace = NULLSESSION;
#endif
static char *DumpAddr = NULL; /* Memory dump pointer */
static FILE *Logfp;
time_t StartTime; /* Time that NOS was started */
static int Verbose;
static void ctohex __ARGS((char *buf,int16 c));
static void fmtline __ARGS((int16 addr,char *buf,int16 len));
extern void assign_filenames __ARGS((char *));
static void logcmd __ARGS((char *));
char *Screen_Address(void);
int Numrows,Numcols; /* screen size at startup - WG7J */
struct hist *Histry; /* command recall stuff */
int Histrysize;
int Maxhistory = 10;
#ifdef EMS
int EMS_Available;
#endif
#ifdef XMS
int XMS_Available;
#endif
#ifdef LINUX
static char **origargv;
#endif
/* The text_info before we start JNOS */
struct text_info PrevTi;
#ifdef STATUSWIN
extern char MainStColors,SesStColors;
#endif
#ifdef SPLITSCREEN
extern char MainColors,SplitColors;
void GiveColor(char *s,char *attr);
#endif
int
main(argc,argv)
int argc;
char *argv[];
{
int ForceIndex = 0;
char *inbuf,*intmp;
FILE *fp;
struct mbuf *bp;
int c,i;
#ifdef LINUX
static int oops;
#endif
struct cur_dirs dirs;
#ifdef EMS
unsigned long emssize;
#endif
#ifdef XMS
long XMS_Ret;
#endif
#ifdef LINUX
if (oops++)
{
iostop();
fprintf(stderr, "NOS PANIC: NOS main re-entered.\n");
fflush(stderr);
fflush(stdout);
kill(getpid(), 11);
}
origargv = argv;
#endif
StartTime = time(&StartTime); /* NOS Start_Up time */
#ifdef UNIX
SRANDOM((getpid() << 16) ^ time((long *) 0));
#else
randomize();
#endif
#if defined(__TURBOC__) || defined(__BORLANDC__)
/* Borland's library calls int10. Some vga mode utilities do not
* report the screen sizes correctly into the internal _video structure.
* This can cause the screen size to be faulty in the gettextinfo call.
* Instead, read the BIOS data area to get the correct screen info,
* and update the _video structure for later calls to
* gettextinfo(), clrscr(), etc... - WG7J
*
* If this doesn't work, you can now overwrite the values with
* the -r and -c command line options - WG7J
*/
Numrows = (int) *(char far *)MK_FP(0x40,0x84) + 1;
gettextinfo(&PrevTi);
Numcols = PrevTi.screenwidth;
#ifdef SPLITSCREEN
MainColors = PrevTi.attribute;
MainColors &= 0xf7; /* turn off highlite */
#endif
/*
Numrows = PrevTi.screenheight;
*/
if(Numrows == 1)
Numrows = 25;
#endif
SwapMode = MEM_SWAP;
#ifdef MSDOS
Screen = Screen_Address();
/* If EMS is found, XMS is not used for swapping - WG7J */
#ifdef EMS
if(ememavl(&emssize) == 0) {
EMS_Available = 1;
SwapMode = EMS_SWAP;
}
#endif
#ifdef XMS
if((XMS_Available = Installed_XMS()) != 0)
#ifdef EMS
if(!EMS_Available)
#endif
SwapMode = XMS_SWAP;
#endif
#endif /* MSDOS */
while((c = getopt(argc,argv,"s:d:r:c:f:m:u:w:x:y:z:nbvelti")) != EOF){
switch(c){
#ifdef __TURBOC__
case 'b': /* Use BIOS for screen output */
directvideo = 0;
break;
#endif
case 'c': /* Number of columns on screen */
Numcols = atoi(optarg);
break;
case 'd': /* Root directory for various files */
initroot(optarg);
break;
case 'e': /* Pause after error lines */
ErrorPause = 1;
break;
#if defined(MSDOS) || defined(UNIX)
case 'f':
assign_filenames(optarg);
break;
#endif
case 'i':
ForceIndex = 1;
break;
case 'l': /* Don't remove mail locks */
RmLocks = 0;
break;
#ifdef MSDOS
case 'm': /* Swap mode, 0=EMS (default),1=XMS,2=MEM,3=FILE - WG7J */
i = atoi(optarg);
#ifdef XMS
if(i == 1 && XMS_Available) {
SwapMode = XMS_SWAP;
} else
#endif
if(i == 2)
SwapMode = MEM_SWAP;
else if(i == 3)
SwapMode = FILE_SWAP;
break;
#endif
#ifdef TRACE
case 'n':
Tracesession = 0; /* No session for tracing */
break;
#endif
case 'r': /* Number of rows on screen */
Numrows = atoi(optarg);
break;
case 't':
Step = 1;
/* note fallthrough */
#ifdef STATUSWIN
case 'u': /* No status lines */
StatusLines = atoi(optarg);
if(StatusLines > MAXSTATUSLINES)
StatusLines = MAXSTATUSLINES;
break;
#endif
case 'v':
Verbose = 1;
break;
#ifdef STATUSWIN
/* Color options - WG7J */
case 'w':
GiveColor(optarg,&MainStColors);
MainStColors |= 0x08; /* Turn on highlite, so it shows on b/w */
break;
case 'x':
GiveColor(optarg,&SesStColors);
SesStColors |= 0x08; /* Turn on highlite, so it shows on b/w */
break;
#endif
#ifdef SPLITSCREEN
case 'y':
GiveColor(optarg,&MainColors);
MainColors &= 0xf7; /* Turn off highlite, so high video shows! */
textattr(MainColors); /* Set the color for startup screen ! */
break;
case 'z':
GiveColor(optarg,&SplitColors);
SplitColors |= 0x08; /* Turn on higlite, so it shows on b/w */
break;
#endif
}
}
#if defined(__TURBOC__) || defined(__BORLANDC__)
/* Set the internal structure, in case there was a command
* line overwrite - WG7J
*/
_video.screenheight = (unsigned char)Numrows;
_video.windowx2 = (unsigned char)(Numcols - 1);
_video.windowy2 = (unsigned char)(Numrows - 1);
#endif
ScreenSize = 2 * Numrows * Numcols;
#ifdef STATUSWIN
if(StatusLines > 1) {
#ifdef MAILBOX
StBuf2 = mallocw(Numcols+3);
StLen2 = sprintf(StBuf2,"\r\nBBS:");
if(StatusLines > 2)
#endif
{
StBuf3 = mallocw(Numcols+3);
sprintf(StBuf3,"\r\n");
}
}
#endif
#ifdef MSDOS
#ifdef XMS
if(XMS_Available)
/* Calculate space in kb for screen */
ScreenSizeK = (ScreenSize / 1024) + 1;
#endif
#endif
kinit();
ipinit();
ioinit();
Cmdpp = mainproc("cmdintrp");
Sessions = (struct session *)callocw(Nsessions,sizeof(struct session));
#ifdef TRACE
if(Tracesession)
Trace = newsession(NULLCHAR,TRACESESSION,0);
#endif
Command = Lastcurr = newsession(NULLCHAR,COMMAND,0);
init_dirs(&dirs);
Command->curdirs=&dirs;
/* Flow mode is set AFTER we've read the autoexec file !
* this keeps systems from locking up if the reboot is unattended - WG7J
*/
#ifndef LINUX
Display = newproc("display",250,display,0,NULLCHAR,NULL,0);
#endif
tprintf(Nosversion,Version);
tputs(Version2);
tputs("Copyright 1991 by Phil Karn (KA9Q) and contributors.\n");
#ifdef MSDOS
#ifdef EMS
if(EMS_Available)
tputs("EMS detected.\n");
#endif
#ifdef XMS
if(XMS_Available)
tputs("XMS detected.\n");
#endif
#endif
#ifdef BETA
tputs("\007\007\007\n==> This is a BETA version; be warned ! <==\n\n");
#endif
rflush();
/* Start background Daemons */
{
struct daemon *tp;
for(tp=Daemons;;tp++){
if(tp->name == NULLCHAR)
break;
newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
}
}
if(optind < argc){
/* Read startup file named on command line */
if((fp = fopen(argv[optind],READ_TEXT)) == NULLFILE)
tprintf(NoRead,argv[optind],sys_errlist[errno]);
} else {
/* Read default startup file named in files.c (autoexec.nos) */
if((fp = fopen(Startup,READ_TEXT)) == NULLFILE)
tprintf(NoRead,Startup,sys_errlist[errno]);
}
if(fp != NULLFILE){
inbuf = mallocw(BUFSIZ);
intmp = mallocw(BUFSIZ);
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
strcpy(intmp,inbuf);
if(Verbose){
tputs(intmp);
rflush();
}
/* Are we stepping through autoexec.nos ? - WG7J */
if(Step) {
int c;
Command->ttystate.edit = Command->ttystate.echo = 0;
c = toupper(keywait("Execute cmd ?",1));
Command->ttystate.edit = Command->ttystate.echo = 1;
if(c != 'Y')
continue;
}
if(cmdparse(Cmds,inbuf,NULL) != 0){
tprintf("input line: %s",intmp);
if(ErrorPause)
keywait(NULLCHAR,1);
rflush();
}
}
fclose(fp);
free(inbuf);
free(intmp);
}
/* Log that we started nos, but do this after the config file is read
* such that logging can be disabled - WG7J
*/
log(-1,"JNOS %s was started",Version);
/* Update .txt files that have old index files - WG7J */
UpdateIndex(NULL,ForceIndex);
if(RmLocks)
RemoveMailLocks();
Mprunning = 1; /* we are on speed now */
/* N7IPB - If lots of output generated during startup we have to wait
* for it all to be output before turning on 'more'
*/
pause(1000);
Command->flowmode = 1; /* set 'more' paging on command screen */
/* Now loop forever, processing commands */
for(;;){
if(DosPrompt)
tprintf("%s ",dirs.dir);
if(!StatusLines)
tprintf("%lu ",coreleft());
tputs(Prompt);
usflush(Command->output);
if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
logcmd(bp->data);
(void)cmdparse(Cmds,bp->data,Lastcurr);
free_p(bp);
}
}
}
/* Keyboard input process */
/* Modified to support F-key session switching,
* from the WNOS3 sources - WG7J
*/
void
keyboard(i,v1,v2)
int i;
void *v1;
void *v2;
{
int c;
struct mbuf *bp;
int j,k;
struct session *sp;
#ifdef STATUSWIN
int newsession;
#endif
/* Keyboard process loop */
for(;;){
c = kbread();
#ifdef STATUSWIN
newsession = 0;
#endif
#if(!defined(MSDOS) || defined(ESCAPE))
if(c == Escape && Escape != 0)
c = -2;
#endif
if(c == -2 && Current != Command){
/* Save current tty mode and set cooked */
Lastcurr = Current;
Current = Command;
swapscreen(Lastcurr,Current);
#ifdef STATUSWIN
newsession = 1;
#endif
/* set 'more' paging on command screen */
Command->flowmode = 1;
}
if((c < -2) && (c > -12)) { /* F1 to F9 pressed */
#ifdef TRACE
/* If F9 is pressed, -11 is returned and we swap to Trace - WG7J */
if(c == -11 && Tracesession) {
if(Current != Trace) {
/* Save current tty mode and set cooked */
swapscreen(Current,Trace);
Lastcurr = Current;
Current = Trace;
#ifdef STATUSWIN
newsession = 1;
#endif
/* turn off 'more' paging on trace screen */
Trace->flowmode = 0;
} else {
/* Toggle back to previous session */
Current = Lastcurr;
Lastcurr = Trace;
swapscreen(Lastcurr,Current);
#ifdef STATUSWIN
newsession = 1;
#endif
}
} else {
#endif
/* Swap directly to F-key session - WG7J */
k = (-1 * c) - 2;
for(sp = Sessions, j = 0; sp < &Sessions[Nsessions]; sp++) {
if(sp->type == COMMAND)
continue;
j++;
if(sp->type != FREE && j == k) {
Lastcurr = Current;
Current = sp;
swapscreen(Lastcurr,Current);
#ifdef STATUSWIN
newsession = 1;
#endif
break;
}
}
#ifdef TRACE
}
#endif
}
#ifdef STATUSWIN
if(newsession)
UpdateStatus();
#endif
Current->row = Numrows - 1 - StatusLines;
psignal(&Current->row,1);
if(c >= 0){
#ifdef LINUX
if (Current->morewait) /* end display pause, if any */
Current->morewait = 2;
#endif
/* If the screen driver was in morewait state, this char
* has woken him up. Toss it so it doesn't also get taken
* as normal input. If the char was a command escape,
* however, it will be accepted; this gives the user
* a way out of lengthy output.
*/
if(!Current->morewait && (bp = ttydriv(Current,c)) != NULLBUF)
send_mbuf(Current->input,bp,0,NULLCHAR,0);
}
}
}
extern int Kblocked;
extern char *Kbpasswd;
#ifdef LOCK
/*Lock the keyboard*/
int
dolock(argc,argv,p)
int argc;
char *argv[];
void *p;
{
extern char Noperm[];
/*allow only keyboard users to access the lock command*/
if(Curproc->input != Command->input) {
tputs(Noperm);
return 0;
}
if(argc == 1) {
if(Kbpasswd == NULLCHAR)
tputs("Set password first\n");
else {
Kblocked = 1;
tputs("Keyboard locked\n");
Command->ttystate.echo = 0; /* Turn input echoing off! */
}
return 0;
}
if(argc == 3) {
if(*argv[1] == 'p') { /*set the password*/
if(Kbpasswd != NULLCHAR){
free(Kbpasswd);
Kbpasswd = NULLCHAR; /* reset the pointer */
}
if(!strlen(argv[2]))
return 0; /* clearing the buffer */
Kbpasswd = strdup(argv[2]);
return 0;
}
}
tputs("Usage: lock password \"<unlock password>\"\n"
"or 'lock' to lock the keyboard\n");
return 0;
}
#endif
/*this is also called from the remote-server for the 'exit' command - WG7J*/
void
where_outta_here(resetme)
int resetme;
{
time_t StopTime;
FILE *fp;
char *inbuf,*intmp;
/* Execute sequence of commands taken from file "~/onexit.nos" */
/* From iw0cnb */
if((fp = fopen(Onexit,READ_TEXT)) != NULLFILE){
inbuf = mallocw(BUFSIZ);
intmp = mallocw(BUFSIZ);
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
strcpy(intmp,inbuf);
if(Verbose){
tputs(intmp);
rflush();
}
if(cmdparse(Cmds,inbuf,NULL) != 0){
tprintf("input line: %s",intmp);
}
}
fclose(fp);
free(inbuf);
free(intmp);
}
StopTime = time(&StopTime);
main_exit = TRUE; /* let everyone know we're out of here */
reset_all();
if(Dfile_updater != NULLPROC)
alert(Dfile_updater,0); /* don't wait for timeout */
pause(3000); /* Let it finish */
#ifdef TRACE
shuttrace();
#endif
log(-1,"JNOS was stopped");
#ifdef LINUX
detach_all_asy(); /* make sure everything is unlocked */
pwait(NULL);
#endif
iostop();
if(resetme)
#ifdef LINUX
{
if (fork() == 0)
abort();
execvp(origargv[0], origargv); /* re-run NOS */
}
#else
sysreset();
#endif
#ifdef MSDOS
#ifdef EMS
effreeall();
#endif
#ifdef XMS
/* Free any possible XMS used for the screen */
Free_Screen_XMS();
#endif
#endif
window(1,1,Numcols,Numrows);
textattr(PrevTi.attribute);
clrscr();
exit(0);
}
int
doexit(argc,argv,p)
int argc;
char *argv[];
void *p;
{
time_t nowtime, elapsedtime;
unsigned int days,hrs,mins,secs;
if(strnicmp(Curproc->name, "at ",3) == 0) /* From the AT command */
where_outta_here(0);
if(Curproc->input == Command->input) { /* From keyboard */
Command->ttystate.edit = Command->ttystate.echo = 0;
if(toupper(keywait("Are you sure? ",0))=='Y') {
nowtime = time(&nowtime); /* current time */
elapsedtime = nowtime - StartTime; /* nos elapsed time */
secs = (unsigned int)(elapsedtime % 60);
elapsedtime = elapsedtime / 60;
mins = (unsigned int)(elapsedtime % 60);
elapsedtime = elapsedtime / 60;
hrs = (unsigned int)(elapsedtime % 24);
elapsedtime = elapsedtime / 24;
days = (unsigned int) elapsedtime;
tprintf("JNOS Exiting - Runtime => %u days:%02u hours:%02u minutes:%02u seconds.\n",days,hrs,mins,secs);
where_outta_here(0); /*No reset!*/
}
Command->ttystate.edit = Command->ttystate.echo = 1;
return 0;
}
/* Anything else; probably mailbox-sysop */
return -2;
}
extern char Chostname[];
int
dohostname(argc,argv,p)
int argc;
char *argv[];
void *p;
{
#ifdef CONVERS
char *cp;
#endif
if(argc < 2)
tprintf("%s\n",Hostname);
else {
struct iface *ifp;
char *name;
if((ifp = if_lookup(argv[1])) != NULLIF){
if((name = resolve_a(ifp->addr, FALSE)) == NULLCHAR){
tputs("Interface address not resolved\n");
return 1;
} else {
if(Hostname != NULLCHAR)
free(Hostname);
Hostname = name;
tprintf("Hostname set to %s\n", name );
}
} else {
if(Hostname != NULLCHAR)
free(Hostname);
Hostname = strdup(argv[1]);
/* Remove trailing dot */
if(Hostname[strlen(Hostname)] == '.')
Hostname[strlen(Hostname)] = '.';
}
#ifdef CONVERS
/* If convers hostname not set yet, set it to first 10 chars
* of the hostname. If there are '.' from the right, cut off
* before that. - WG7J
*/
if(Chostname[0] == '\0') {
strncpy(Chostname,Hostname,CNAMELEN);
if((cp = strrchr(Chostname,'.')) != NULLCHAR)
*cp = '\0';
}
#endif
}
return 0;
}
int Uselog = 1;
int
dolog(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&Uselog,"disk logging",argc,argv);
}
void log(int s,char *fmt, ...)
{
va_list ap;
char *cp, ML[FILE_PATH_SIZE];
time_t t;
int i;
struct sockaddr fsocket;
FILE *fp;
if(!Uselog)
return;
time(&t);
cp = ctime(&t);
sprintf(ML,"%s/%2.2s%3.3s%2.2s",LogsDir,cp+8,cp+4,cp+22);
if ((fp = fopen(ML,APPEND_TEXT)) == NULLFILE)
return;
i = SOCKSIZE;
fprintf(fp,"%9.9s",cp+11);
if(getpeername(s,(char *)&fsocket,&i) != -1)
fprintf(fp, " %s",psocket(&fsocket));
fprintf(fp, " - ");
va_start(ap,fmt);
vfprintf(fp,fmt,ap);
va_end(ap);
fprintf(fp,"\n");
fclose(fp);
}
int
dohelp(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct cmds *cmdp;
int i;
char buf[FILE_PATH_SIZE];
char **pargv;
FILE *fp;
struct mbx *m;
/* ? => display compiled-command names
* help =or= help ? => show /help/help
* help X => show /help/X
*/
if(*argv[0] == '?' ) {
tputs("Main commands:\n");
memset(buf,' ',sizeof(buf));
buf[75] = '\n';
buf[76] = '\0';
for(i=0,cmdp = Cmds;cmdp->name != NULL;cmdp++,i = (i+1)%5){
strncpy(&buf[i*15],cmdp->name,strlen(cmdp->name));
if(i == 4){
tputs(buf);
memset(buf,' ',sizeof(buf));
buf[75] = '\n';
buf[76] = '\0';
}
}
if(i != 0)
tputs(buf);
} else {
sprintf(buf,"%s/%s",CmdsHelpdir,"help"); /* default */
if(argc > 1) {
for(i=0; Cmds[i].name != NULLCHAR; ++i)
if(!strncmp(Cmds[i].name,argv[1],strlen(argv[1]))) {
if(*argv[1] != '?')
sprintf(buf,"%s/%s",CmdsHelpdir,Cmds[i].name);
break;
}
if(Cmds[i].name == NULLCHAR) {
tputs("Unknown command; type \"?\" for list\n");
return 0;
}
}
#if defined MORESESSION || defined DIRSESSION || defined FTPSESSION
pargv = (char **)callocw(2,sizeof(char *));
pargv[1] = strdup(buf);
if(Curproc->input == Command->input) { /* from console? */
newproc("more",512,(void (*)__ARGS((int,void *,void *)))morecmd,2,(void *)pargv,p,1);
} else {
morecmd(2,pargv,p);
free(pargv[1]);
free(pargv);
}
#else
if((fp = fopen(buf,READ_TEXT)) == NULLFILE)
tprintf(NoRead,buf,sys_errlist[errno]);
else {
for (m=Mbox; m!=NULLMBX; m=m->next)
if (m->proc == Curproc) break;
sendfile(fp,Curproc->output,ASCII_TYPE,0,m);
fclose(fp);
}
#endif
}
return 0;
}
/* Attach an interface
* Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
*/
int
doattach(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Attab,argc,argv,p);
}
/* Manipulate I/O device parameters */
int
doparam(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int param,set;
int32 val;
register struct iface *ifp;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badinterface,argv[1]);
return 1;
}
if(ifp->ioctl == NULL){
tputs("Not supported\n");
return 1;
}
if(argc < 3){
for(param=1;param<=16;param++){
val = (*ifp->ioctl)(ifp,param,FALSE,0L);
if(val != -1)
tprintf("%s: %ld\n",parmname(param),val);
}
return 0;
}
param = devparam(argv[2]);
if(param == -1){
tprintf("Unknown parameter %s\n",argv[2]);
return 1;
}
if(argc < 4){
set = FALSE;
val = 0L;
} else {
set = TRUE;
val = atol(argv[3]);
}
val = (*ifp->ioctl)(ifp,param,set,val);
if(val == -1){
tprintf("Parameter %s not supported\n",argv[2]);
} else {
tprintf("%s: %ld\n",parmname(param),val);
}
return 0;
}
/* Display or set IP interface control flags */
int
domode(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct iface *ifp;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badinterface,argv[1]);
return 1;
}
if(argc < 3){
tprintf("%s: %s\n",ifp->name,
(ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
return 0;
}
switch(argv[2][0]){
case 'v':
case 'c':
case 'V':
case 'C':
ifp->flags |= CONNECT_MODE;
break;
case 'd':
case 'D':
ifp->flags &= ~CONNECT_MODE;
break;
default:
tprintf("Usage: %s [vc | datagram]\n",argv[0]);
return 1;
}
return 0;
}
#if (!defined(MSDOS) || defined(ESCAPE))
int
doescape(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2)
tprintf("0x%x\n",Escape);
else
Escape = *argv[1];
return 0;
}
#endif MSDOS
#ifdef REMOTESERVER
extern char *Rempass; /* Remote access password */
char remote_options[] = "a:p:k:s:";
#else
char remote_options[] = "a:p:k:";
#endif
/* Generate system command packet. Synopsis:
* remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
*/
int
doremote(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct sockaddr_in fsock;
int s,c;
char *data,x;
int16 port,len;
char *key = NULLCHAR;
int klen;
int32 addr = 0;
char *cmd,*host;
port = IPPORT_REMOTE; /* Set default */
optind = 1; /* reinit getopt() */
while((c = getopt(argc,argv,remote_options)) != EOF){
switch(c){
case 'a':
if((addr = resolve(optarg)) == 0){
tprintf(Badhost,optarg);
return -1;
}
break;
case 'p':
port = atoi(optarg);
break;
case 'k':
key = optarg;
klen = strlen(key);
break;
#ifdef REMOTESERVER
case 's':
Rempass = strdup(optarg);
return 0; /* Only set local password */
#endif
}
}
if(optind > argc - 2){
tputs("Insufficient args\n");
return -1;
}
host = argv[optind++];
cmd = argv[optind];
if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
tputs("socket failed\n");
return 1;
}
len = 1;
/* Did the user include a password or kickme target? */
if(addr != 0 && cmd[0] == 'k')
len += sizeof(int32);
if(key != NULLCHAR && (cmd[0] == 'r' || cmd[0] == 'e'))
len += klen;
if(len == 1)
data = &x;
else
data = mallocw(len);
fsock.sin_family = AF_INET;
if((fsock.sin_addr.s_addr = resolve(host)) == 0){
tprintf(Badhost,host);
goto cleanup;
}
fsock.sin_port = port;
switch(cmd[0]){
case 'r':
data[0] = SYS_RESET;
if(key != NULLCHAR)
strncpy(&data[1],key,klen);
break;
case 'e':
data[0] = SYS_EXIT;
if(key != NULLCHAR)
strncpy(&data[1],key,klen);
break;
case 'k':
data[0] = KICK_ME;
if(addr != 0)
put32(&data[1],addr);
break;
default:
tprintf("Unknown command %s\n",cmd);
goto cleanup;
}
/* Form the command packet and send it */
if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
tprintf("sendto failed: %s\n",sys_errlist[errno]);
goto cleanup;
}
cleanup:
if(data != &x)
free(data);
close_s(s);
return 0;
}
#if defined MORESESSION || defined DIRSESSION || defined FTPSESSION
int
morecmd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct session *sp;
FILE *fp;
char buf[81],fname[128];
int row;
int usesession = 0;
/* Use a session if this comes from console - WG7J*/
if(Curproc->input == Command->input) {
usesession = 1;
if((sp = newsession(argv[1],MORE,0)) == NULLSESSION){
return 1;
}
/* Put tty into raw mode so single-char responses will work */
sp->ttystate.echo = sp->ttystate.edit = 0;
row = Numrows - 1 - StatusLines;
}
strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
if((fp = fopen(fname,READ_TEXT)) == NULLFILE){
tprintf(NoRead,fname,sys_errlist[errno]);
if(usesession) {
keywait(NULLCHAR,1);
freesession(sp);
}
return 1;
}
while(fgets(buf,sizeof(buf),fp),!feof(fp)){
if((argc < 3) || (strstr(buf,argv[2])!=NULLCHAR)) {
tputs(buf);
if(usesession) {
if(--row == 0){
row = keywait(TelnetMorePrompt,0);
switch(row){
case -1:
case 'q':
case 'Q':
goto done;
case '\n':
case '\r':
row = 1;
break;
case ' ':
default:
row = Numrows - 1 - StatusLines;
}
}
}
}
}
done: fclose(fp);
if(usesession) {
keywait(NULLCHAR,1);
freesession(sp);
}
return 0;
}
#endif /* MORE | DIR | FTP SESSION */
#ifdef MORESESSION
int
domore(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char **pargv;
int i;
if(Curproc->input == Command->input) {
/* Make private copy of argv and args,
* spawn off subprocess and return.
*/
pargv = (char **)callocw(argc,sizeof(char *));
for(i=0;i<argc;i++)
pargv[i] = strdup(argv[i]);
newproc("more",512,(void (*)__ARGS((int,void *,void *)))morecmd,argc,(void *)pargv,p,1);
} else
morecmd(argc,argv,p);
return 0;
}
#endif /* MORESESSION */
#ifdef ALLCMD
int
dotaillog(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char logfile[129];
time_t t;
char *cp;
/* Create the log file name */
time(&t);
cp = ctime(&t);
sprintf(logfile,"%s/%2.2s%3.3s%2.2s",LogsDir,cp+8,cp+4,cp+22);
argc = 2; /* ignore any provided args */
argv[1] = logfile;
return dotail(argc,argv,p);
}
int
dotail(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register int handle, i;
register unsigned line = 0, rdsize = 2000;
long length;
char *buffer;
buffer = callocw(2000, sizeof (char));
if ((handle = open (argv[1], O_BINARY | O_RDONLY)) == -1) {
tprintf(NoRead,argv[1],sys_errlist[errno]);
free(buffer);
return -1;
}
length = filelength(handle);
if (length > 2000) {
length -= 2000;
} else {
rdsize = (int) length;
length = 0;
}
lseek (handle, length, SEEK_SET);
if (read (handle, buffer, rdsize) == -1) {
tprintf(NoRead,argv[1],sys_errlist[errno]);
close(handle);
free(buffer);
return -1;
}
for (i = rdsize - 1; i > 0; i--) {
if (buffer[i] == '\n')
line++;
if (line == 18)
break;
}
for (; i < rdsize; i++)
tputc(buffer[i]);
tputc('\n');
close(handle);
free(buffer);
return 0;
}
#endif /*ALLCMD*/
/* No-op command */
int
donothing(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return 0;
}
/* Pause command */
int
dopause(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int secs;
if(argc > 1) {
secs = atoi(argv[1]);
if (secs > 0) pause(1000L * secs);
}
return 0;
}
#ifdef MAILERROR
static int SendError = 1;
int doerror(int argc,char *argv[],void *p) {
return setbool(&SendError,"Mail errors",argc,argv);
}
/* Mail a system message to the sysop - WG7J */
void
mail_error(char *fmt, ...)
{
FILE *wrk,*txt;
va_list ap;
char *cp;
long t,msgid;
char fn[128];
if(!SendError)
return;
/* Get current time */
time(&t);
/* get the message id for this message */
msgid = get_msgid();
/* Create the smtp work file */
sprintf(fn,"%s/%ld.wrk",Mailqdir,msgid);
if((wrk = fopen(fn,"w")) == NULL)
return;
/* Create the smtp text file */
sprintf(fn,"%s/%ld.txt",Mailqdir,msgid);
if((txt = fopen(fn,"w")) == NULL) {
fclose(wrk);
return;
}
/* Fill in the work file */
fprintf(wrk,"%s\nMAILER-DAEMON@%s\nsysop@%s",Hostname,Hostname,Hostname);
fclose(wrk);
/* Fill in the text file headers */
fprintf(txt,"%s%s",Hdrs[DATE],ptime(&t));
fprintf(txt,"%s<%ld@%s>\n",Hdrs[MSGID],msgid,Hostname);
fprintf(txt,"%sMAILER-DAEMON@%s\n",Hdrs[FROM],Hostname);
fprintf(txt,"%ssysop@%s\n",Hdrs[TO],Hostname);
fprintf(txt,"%sSystem message\n\n",Hdrs[SUBJECT]);
/* Print the text body */
cp = ctime(&t);
fprintf(txt,"On %s",cp);
va_start(ap,fmt);
vfprintf(txt,fmt,ap);
va_end(ap);
fputc('\n',txt);
fclose(txt);
/* Now kick the smtp server */
smtptick(NULL);
}
#endif /* MAILERROR */
int
dosource(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int linenum = 0;
char *inbuf,*intmp;
FILE *fp;
/* Read command source file */
if((fp = fopen(argv[1],READ_TEXT)) == NULLFILE){
tprintf(NoRead,argv[1],sys_errlist[errno]);
return 1;
}
inbuf = malloc(BUFSIZ);
intmp = malloc(BUFSIZ);
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
strcpy(intmp,inbuf);
linenum++;
if(Verbose)
tputs(intmp);
if(cmdparse(Cmds,inbuf,NULL) != 0){
tprintf("*** file \"%s\", line %d: %s\n",
argv[1],linenum,intmp);
}
}
fclose(fp);
free(inbuf);
free(intmp);
return 0;
}
#ifdef TTYLINKSERVER
/* if unattended mode is set - restrict ax25, telnet and maybe other sessions */
int
doattended(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&Attended,"Attended flag",argc,argv);
}
#endif
/* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
int
dothirdparty(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&ThirdParty,"Third-Party mail flag",argc,argv);
}
#ifdef ALLCMD
int
domdump(argc,argv,p)
int argc;
char *argv[];
void *p;
{
unsigned int i;
char *addr,*cp;
unsigned int segment,offset;
unsigned int len = 8 * 16; /* default is 8 lines of hex dump */
if(argc < 2 || argc > 3) {
tputs("Usage:- dump <hex-address | .> [decimal-range] \n");
return 0;
}
if(argv[1][0] == '.')
addr = DumpAddr; /* Use last end address */
else {
if((cp=strchr(argv[1],':')) != NULL) {
/* Interpret segment:offset notation */
*cp++ = '\0';
segment = (unsigned int) htol(argv[1]);
offset = (unsigned int) htol(cp);
addr = MK_FP(segment,offset);
} else
addr = ltop(htol(argv[1])); /* get address of item being dumped */
}
if(argc == 3) {
len = atoi(argv[2]);
len = ((len + 15) >> 4) << 4; /* round up to modulo 16 */
}
if(len < 1 || len > 256) {
tputs("Invalid dump range. Valid is 1 to 256\n");
return 0;
}
tprintf(" Main Memory Dump Of Location %Fp\n", addr);
tputs("Addr (offset) Hexadecimal Ascii\n");
tputs("---- ----------- -----\n\n");
for(i = 0; i < len; i += 16)
fmtline(i, (char *)(addr + i), 16);
DumpAddr = (char *)(addr + i); /* update address */
return 0;
}
/* Print a buffer up to 16 bytes long in formatted hex with ascii
* translation, e.g.,
* 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
*/
static void
fmtline(addr,buf,len)
int16 addr;
char *buf;
int16 len;
{
char line[81];
register char *aptr,*cptr;
register char c;
memset(line,' ',sizeof(line));
ctohex(line,(int16)hibyte(addr));
ctohex(line+2,(int16)lobyte(addr));
aptr = &line[6];
cptr = &line[55];
while(len-- != 0){
c = *buf++;
ctohex(aptr,(int16)uchar(c));
aptr += 3;
c &= 0x7f;
if((c > 0x1f) && (c < 0x7f))
*cptr++ = c;
else
*cptr++ = '.';
}
*cptr++ = '\0';
tprintf("%s\n",line);
}
/* Convert byte to two ascii-hex characters */
static void
ctohex(buf,c)
register char *buf;
register int16 c;
{
static char hex[] = "0123456789abcdef";
*buf++ = hex[hinibble(c)];
*buf = hex[lonibble(c)];
}
#endif
int
dowrite(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int s;
struct mbx *m;
if((s = atoi(argv[1])) == 0) { /* must be a name */
#ifdef MAILBOX
/* check the mailbox users */
for(m=Mbox;m;m=m->next){
if(!stricmp(m->name,argv[1]))
break;
}
if(!m)
return 0;
s = m->user;
#else
return 0;
#endif
}
usprintf(s,"*** Msg from SYSOP: %s\n",argv[2]);
usflush(s);
return 0;
}
#ifdef MAILBOX
/* write a message to all nodeshell users
* argv[1] is the message.
*/
int
dowriteall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
for(m=Mbox;m;m=m->next){
if(m->sid & MBX_SID)
continue;
usprintf(m->user,"*** Msg from SYSOP: %s\n",argv[1]);
usflush(m->user);
}
return 0;
}
#endif
int
dostatus(argc,argv,p)
int argc;
char *argv[];
void *p;
{
time_t nowtime, elapsedtime, nosseconds;
unsigned int days,hrs,mins,secs;
nowtime = time(&nowtime); /* current time */
nosseconds = secclock(); /* Current NOS lifetime */
elapsedtime = nowtime - StartTime; /* nos elapsed time */
tprintf(Nosversion,Version);
tputs(Version2);
tprintf("Tty: %d rows, %d columns\n",Numrows,Numcols);
#ifdef MSDOS
tprintf(NosLoadInfo, _CS, _DS);
#endif
tprintf("\nThe system time is %s", ctime(&nowtime));
tprintf("NOS was started on %s\n", ctime(&StartTime));
secs = (unsigned int) (elapsedtime % 60);
elapsedtime = elapsedtime / 60;
mins = (unsigned int) (elapsedtime % 60);
elapsedtime = elapsedtime / 60;
hrs = (unsigned int) (elapsedtime % 24);
elapsedtime = elapsedtime / 24;
days = (unsigned int) elapsedtime;
tprintf("Elapsed time => %u days:%02u hours:%02u minutes:%02u seconds.\n", days,hrs,mins,secs);
if(nosseconds < elapsedtime)
tprintf("NOS has lost %lu seconds in missed clock ticks!\n", \
elapsedtime - nosseconds);
tputc('\n');
#ifdef TTYLINKSERVER
tprintf("The station is currently %sttended.\n", Attended ? "A" : "Una");
#endif
#ifdef ALLCMD
tputs("The 'Message Of The Day' is ");
if(Motd != NULLCHAR)
tprintf("\n%s",Motd);
else
tputs("not set!\n");
#endif
#ifdef __TURBOC__
dofstat(); /* print status of open files */
#endif
return 0;
}
#ifdef ALLCMD
int
domotd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc > 2) {
tputs("Usage: motd \"<your message>\"\n");
return 1;
}
if(argc < 2) {
if(Motd != NULLCHAR)
tputs(Motd);
} else {
if(Motd != NULLCHAR){
free(Motd);
Motd = NULLCHAR; /* reset the pointer */
}
if(!strlen(argv[1]))
return 0; /* clearing the buffer */
Motd = mallocw(strlen(argv[1])+5); /* allow for the EOL char etc */
strcpy(Motd, argv[1]);
strcat(Motd, "\n"); /* add the EOL char */
}
return 0;
}
#endif /*ALLCMD*/
#ifdef __TURBOC__
/*
* Fstat utility code.
* Converted to go into NOS by Kelvin Hill - G1EMM April 9, 1990
*/
extern unsigned char _osmajor;
static char *localcopy(char far *);
static char *progname(unsigned int);
#ifdef __TURBOC__
extern char *Taskers[];
extern int Mtasker;
int
dofstat()
{
union REGS regs;
struct SREGS segregs;
char far *pfiletab, far * pnext, far * fp;
char far *name, file[13], far * plist, far * entry;
char ownername[9], ownerext[5];
int nfiles, i, j, numhandles, entrylen;
unsigned int access, devinfo, progpsp;
long length, offset;
int heading = 0;
regs.h.ah = 0x52; /* DOS list of lists */
intdosx(®s, ®s, &segregs);
/* make a pointer to start of master list */
plist = (char far *) MK_FP(segregs.es, regs.x.bx);
/* pointer to start of file table */
pfiletab = (char far *) MK_FP(*(int far *) (plist + 6), *(int far *) (plist + 4));
switch (_osmajor) {
case 2:
entrylen = 40; /* DOS 2.x */
break;
case 3:
entrylen = 53; /* DOS 3.x */
break;
case 4:
case 5: /* DOS 5.x - like dos 4.x */
case 6: /* and NOW DOS 6.0 also */
entrylen = 59; /* DOS 4.x - I do not know what is in the
* extra 6 bytes */
break;
default:
tprintf("File table not available under %s\n",Taskers[Mtasker]);
return 1;
}
for (;;) {
/* pointer to next file table */
pnext = (char far *) MK_FP(*(int far *) (pfiletab + 2), *(int far *) (pfiletab + 0));
nfiles = *(int far *) (pfiletab + 4);
#ifdef DEBUG
tprintf("\nFile table at %Fp entries for %d files\n", pfiletab, nfiles);
#endif
for (i = 0; i < nfiles; i++) {
/*
* cycle through all files, quit when we reach an
* unused entry
*/
entry = pfiletab + 6 + (i * entrylen);
if (_osmajor >= 3) {
name = entry + 32;
strncpy(file, localcopy(name), 11);
file[11] = '\0';
numhandles = *(int far *) (entry + 0);
access = (int) *(char far *) (entry + 2);
length = *(long far *) (entry + 17);
offset = *(long far *) (entry + 21);
devinfo = *(int far *) (entry + 5);
progpsp = *(int far *) (entry + 49);
} else {
name = entry + 4;
strncpy(file, localcopy(name), 11);
file[11] = '\0';
numhandles = (int) *(char far *) (entry + 0);
access = (int) *(char far *) (entry + 1);
length = *(long far *) (entry + 19);
offset = *(long far *) (entry + 36);
devinfo = (int) *(char far *) (entry + 27);
}
if ((strlen(file) > 0) && (numhandles > 0) && !(devinfo & 0x80)) {
if(!heading) {
tputc('\n');
tputs(" Table of Open Files.\n");
tputs(" --------------------\n");
tputs("Name length offset hnd acc PSP device type/owner\n");
tputs("---- ------ ------ --- --- --- -----------------\n");
heading++; /* header now printed */
}
tprintf("%8.8s.%3.3s %8ld %8ld %2d ",
file, &file[8], length, offset, numhandles);
switch (access) {
case 0:
tputs("r ");
break;
case 1:
tputs("w ");
break;
case 2:
tputs("rw ");
break;
default:
tputs(" ");
}
if (_osmajor >= 3)
tprintf("%04X ", progpsp);
else
tputs("---- ");
tprintf("drive %c: ", 'A' + (devinfo & 0x1F));
if (devinfo & 0x8000)
tputs("(network) ");
if (_osmajor >= 3) {
/*
* only DOS 3+ can find out
* the name of the program
*/
fnsplit(progname(progpsp), NULL, NULL, ownername, ownerext);
tprintf(" [%s%s]\n", strlwr(ownername), strlwr(ownerext));
} else {
tputc('\n');
}
}
if (strlen(file) == 0)
return 0;
}
pfiletab = pnext;
}
}
#endif /* __TURBOC__ */
/* Make a copy of a string pointed to by a far pointer */
static char *
localcopy(s)
char far *s;
{
static char localstring[256];
char far *p = s;
char *l = localstring;
int i = 0;
while (*p != NULL && i++ < 255) {
*l++ = *p++;
}
*l = '\0';
return (localstring);
}
/*
* Return a near pointer to a character string with the full path name of the
* program whose PSP is given in the argument. If the argument is invalid,
* this may return gibberish but I don't know how to tell Offset 0x2C in the
* PSP in the segment address of the environment of a program. Beyond the
* last environment string is a null marker, a word count (usually 1), then
* the full pathname of the owner of the environment This only works for DOS
* 3+
*/
static char *
progname(pid)
unsigned int pid;
{
unsigned far *envsegptr; /* Pointer to seg address of
* environment */
char far *envptr; /* Pointer to pid's environment */
unsigned far *envsizeptr; /* Pointer to environment size */
unsigned envsize;/* Size of pid's environment */
unsigned ppid; /* Parent psp address */
/* find the parent process psp at offset 0x16 of the psp */
ppid = *(unsigned far *) MK_FP(pid, 0x16);
/* find the environment at offset 2Ch of the psp */
envsegptr = (unsigned far *) MK_FP(pid, 0x2C);
envptr = (char far *) MK_FP(*envsegptr, 0);
/*
* Make a pointer that contains the size of the environment block.
* Must point back one paragraph (to the environments MCB plus three
* bytes forward (to the MCB block size field).
*/
envsizeptr = (unsigned far *) MK_FP(*envsegptr - 1, 0x3);
envsize = *envsizeptr * 16; /* x 16 turns it into bytes */
while (envsize > 0) {
/* search for end of environment block, or NULL */
while (--envsize && *envptr++);
/*
* Now check for another NULL immediately following the first
* one located and a word count of 0001 following that.
*/
if (!*envptr && *(unsigned far *) (envptr + 1) == 0x1) {
envptr += 3;
break;
}
}
if (envsize > 0) {
/* Owner name found - return it */
return (localcopy(envptr));
} else {
if (pid == ppid) {
/*
* command.com doesn't leave it's name around, but if
* pid = ppid then we know we have a shell
*/
return ("-shell-");
} else {
return ("unknown");
}
}
}
#endif /*__TURBOC__*/
int
doprompt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&DosPrompt,"prompt",argc,argv);
}
/* Command history, see also pc.c - WG7J */
void logcmd(char *cmd) {
struct hist *new;
char *cp;
if(!Maxhistory) /* don't keep history */
return;
/* Get rid of \n; this is also done in cmdparse().
* We HAVE to do this here, since the string is NOT null-terminated when
* it comes from recv_mbuf() !!!! rip() makes it nullterminated.
*/
rip(cmd);
cp = cmd;
while(*cp == ' ' || *cp == '\t')
cp++;
if(!*cp) /* Empty command */
return;
if(Histrysize < Maxhistory) { /* Add new one */
Histrysize++;
if(!Histry) { /* Empty list */
/* Initialize circular linked list */
Histry = mallocw(sizeof(struct hist));
Histry->next = Histry->prev = Histry;
} else {
new = mallocw(sizeof(struct hist));
/* Now link it in */
Histry->next->prev = new;
new->next = Histry->next;
new->prev = Histry;
Histry->next = new;
Histry = new;
}
} else {
/* Maximum number stored already, use the oldest entry */
Histry = Histry->next;
free(Histry->cmd);
}
Histry->cmd = strdup(cp);
}
int
dohistory(int argc,char *argv[],void *p) {
struct hist *h;
int num;
if(argc > 1) {
Maxhistory = atoi(argv[1]);
return 0;
}
tprintf("Max recall %d\n",Maxhistory);
if((h = Histry) == NULL)
return 0;
num = 0;
do {
tprintf("%.2d: %s\n",num++,h->cmd);
h = h->prev;
} while(h != Histry);
return 0;
}
#ifdef __BORLANDC__
/* This adds some additional checks to the fopen()
* in the Borland C++ Run Time Library.
* It fixes problem with users trying to open system devices like
* CON, AUX etc and hang a system.
* WG7J, 930205
* reworked by N5KNX 8/94 to allow output to printers iff PRINTEROK is defined,
* AND the printer can accept output. It's still risky; JNOS can lockup if
* the printer won't accept output.
*/
#undef fopen
FILE _FAR *_Cdecl fopen(const char _FAR *__path, const char _FAR *__mode);
static char *InvalidName[] = {
"NUL",
"CON","CON:",
"AUX","AUX:",
"PRN","PRN:",
"LPT1","LPT1:",
"LPT2","LPT2:",
"LPT3","LPT3:",
"COM1","COM1:",
"COM2","COM2:",
"COM3","COM3:",
"COM4","COM4:",
"MOUSE$",
"CLOCK$",
NULLCHAR
};
FILE *newfopen (const char *filename, const char *type) {
char *cp, *cp1;
int i,j;
#include <bios.h>
cp = strrchr(filename, '\\');
cp1 = strrchr(filename, '/');
if (cp < cp1) cp = cp1;
if (cp == NULLCHAR) cp = (char *)filename;
else cp++;
if ((cp1 = strchr(cp, '.')) == NULLCHAR) j = strlen(cp);
else j = (int)(cp1 - cp);
if (j==0) return NULL; /* path is to a dir, or entryname is .XXX, clearly bad */
for(i=0;InvalidName[i] != NULLCHAR;i++)
if(strnicmp(InvalidName[i],cp, j) == 0) {
if (strpbrk(type, "wWaA") == NULLCHAR) return NULL; /* must be writing */
#if defined(PRINTEROK)
j=-1;
if (strnicmp(cp, "prn", 3)==0 ) j=0;
else if (strnicmp(cp, "lpt", 3)==0) j=(*(cp+3) - '1');
if (j>=0 && j<3 && ((i=_bios_printer(2,j,0)&0xb9) == 0x90)) break; /* must be selected, no errors, not busy */
#endif
return NULL;
}
return fopen (filename, type);
}
#endif /* __BORLANDC__ */
#ifdef REPEATSESSION
#if defined(__TURBOC__) && !defined(__BORLANDC__)
/* N5KNX: TurboC 2.0 lacks _setcursortype(), which we supply here for dorepeat */
void _setcursortype(int style)
{
/* From TurboC++ conio.h: */
#define _NOCURSOR 0
#define _SOLIDCURSOR 1
#define _NORMALCURSOR 2
/* Int 0x10 reg cx codes: */
#define STD_CURSOR 0x0607
#define BLK_CURSOR 0x0006
#define NO_CURSOR 0x2607
union REGS regs;
if (style == _NOCURSOR) regs.x.cx = NO_CURSOR;
else if (style == _SOLIDCURSOR) regs.x.cx = BLK_CURSOR;
else if (style == _NORMALCURSOR) regs.x.cx = STD_CURSOR;
else return;
regs.x.ax = 0x0100; /* set cursor */
int86(0x10, ®s, ®s);
}
#endif
/* Repeat a command - taken from 930104 KA9Q NOS
WA3DSP 1/93
*/
int
dorepeat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 interval;
int ret;
struct session *sp;
if(isdigit(argv[1][0])){
interval = atol(argv[1]);
argc--;
argv++;
} else {
interval = MSPTICK;
}
if((sp = newsession(argv[2],REPEAT,1)) == NULLSESSION){
tputs("Too many sessions\n");
return 1;
}
_setcursortype(_NOCURSOR);
while(sp==Current){
/* clrscr(); */
/* gotoxy seems to work better - turn cursor off?? */
gotoxy(1,1);
ret = subcmd(Cmds,argc,argv,p);
if(ret != 0 || pause(interval) == -1)
break;
}
_setcursortype(_NORMALCURSOR);
freesession(sp);
return 0;
}
#endif /* REPEATSESSION */
/* Index given mailbox files */
int doindex(int argc,char *argv[],void *p) {
int i;
for(i=1;i<argc;i++) {
if(*argv[i] == '*') {
UpdateIndex(NULL,1);
/* No reason to do others */
return 0;
} else {
dirformat(argv[i]);
/* Attempt to lock the mail file! */
if(mlock(Mailspool,argv[i])) {
tprintf("Can not lock '%s/%s.txt'!\n",Mailspool,argv[i]);
continue;
}
if(IndexFile(argv[i],0) != 0)
tprintf("Error writing index file for %s\n",argv[i]);
/* Remove the lock */
rmlock(Mailspool,argv[i]);
}
}
return 0;
}
/* interpret a string "f+b", where f and b are numbers indicating
* foreground and background colors to make up the text attribute
*/
void GiveColor(char *s,char *attr) {
char *cp;
if((cp=strchr(s,'+')) != NULL) {
*cp++ = '\0';
*attr = (char) atoi(s) & 0x0f; /* Foreground color */
*attr += ((char) atoi(cp) & 0x07) << 4; /* Background, no blinking ! */
}
}